/**
 * DSM - Distributed Search Manager
 * Developed by Milspec Research International Pty Ltd
 * $Author: gsingh $
 * $Revision: 1.4 $
 * $Date: 2005/10/06 01:51:03 $
 * (c)Copyright 2004
 * education.au limited
 * DEST
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 * Neither the names education.au limited, DEST nor the names of its
 * contributors may be used to endorse or promote products derived from this
 * software without specific prior written permission.
 * To the extent permitted by law, the copyright owners of this software and
 * its contributors:
 * (i) exclude all warranties in relation to the software; and
 * (ii) exclude liability for all losses, costs, expenses and damages arising
 * in any way from the use of the software whether arising from or in
 * relation to breach of contract, negligence or any other tort, in equity
 * or otherwise. If the software is in breach of a warranty which is
 * implied by law, the copyright owners and contributors liability is
 * limited to the replacement of the software.
 *
 * @author	gsingh
 */

package au.edu.educationau.opensource.dsm.obj;

import java.util.Hashtable;
import java.util.Vector;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import au.edu.educationau.opensource.dsm.util.EducationAuUtils;
import au.edu.educationau.opensource.dsm.util.StringUtils;

/**
 * Handles SOAP requests and creates the search criteria objects that the
 * SearchManagerService can understand
 * 
 */

public class SRWRequestHandler extends DefaultHandler {
	public static final int OPERATION_EXPLAIN = 0;
	public static final int OPERATION_SEARCHRETRIEVE = 1;

	private SearchCriteria criteria = new SearchCriteria();
	private String user = "";
	private String allowDuplicates = "false";
	private int start = 1;
	private int pageSize = 10;
	private long token = 0;
	private String currentElement = "";
	private String attributeVal = "";
	private String rset = "";
	private Vector sources = new Vector();
	private Vector thesauri = new Vector();
	private int operation = OPERATION_SEARCHRETRIEVE;
	private String version = "";
	private String sortKeys = "";
	private String stylesheet = "";
	private Hashtable priorities = new Hashtable();

	/** Returns version */
	public String getVersion() {
		return version;
	}

	/** Returns sortKeys */
	public String getSortKeys() {
		return sortKeys;
	}

	/** Returns the operation */
	public int getOperation() {
		return operation;
	}

	/** Returns the priority for a given key */
	public String getPriority(String key) {
		return (String) priorities.get(key);
	}

	/** Returns the stylesheet */
	public String getStylesheet() {
		return stylesheet;
	}

	/** Returns the assembled search criteria */
	public SearchCriteria getSearchCriteria() {
		return criteria;
	}

	/** Returns the user that initiated this search criteria */
	public String getUser() {
		return user;
	}

	/** Returns the result set view requireed */
	public String getRset() {
		return rset;
	}

	/** Returns if duplicates should be allowed */
	public String getAllowDuplicates() {
		return allowDuplicates;
	}

	/** Returns the requested result start index */
	public int getStart() {
		return start;
	}

	/** Returns the page view size */
	public int getPageSize() {
		return pageSize;
	}

	/** Returns the token sent with this request */
	public long getToken() {
		return token;
	}

	/**
	 * Event based parsing -
	 * 
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void characters(char[] ch, int ch_start, int ch_length) throws SAXException {
		String val = String.copyValueOf(ch, ch_start, ch_length);

		if (currentElement.equals("user")) {
			this.user = val;
		} else if (currentElement.equals("query")) {
			this.criteria.setQuery(val);
		} else if (currentElement.equals("sortKeys")) {
			this.sortKeys = val;
		} else if (currentElement.equals("stylesheet")) {
			this.stylesheet = val;
		} else if (currentElement.equals("version")) {
			this.version = val;
		} else if (currentElement.equals("sr")) {
			this.sources.add(val);
		} else if (currentElement.equals("cs")) {
			this.criteria.setCaseSensitive(val.equals("true"));
		} else if (currentElement.equals("mr")) {
			this.criteria.setMaxResults(EducationAuUtils.getInteger(StringUtils.checkString(val, "100"), 10, 500));
		} else if (currentElement.equals("th")) {
			this.thesauri.add(val);
		} else if (currentElement.equals("kc")) {
			this.criteria.setKeywordConstraint(val);
		} else if (currentElement.equals("ss")) {
			this.criteria.setSearchStrategy(val);
		} else if (currentElement.equals("rset")) {
			this.rset = val;
		} else if (currentElement.equals("startRecord")) {
			this.start = EducationAuUtils.getInteger(val, 1, 500);
		} else if (currentElement.equals("maximumRecords")) {
			this.pageSize = EducationAuUtils.getInteger(val, 10, 500);
		} else if (currentElement.equals("token")) {
			this.token = EducationAuUtils.getLong(val, 0);
		} else if (currentElement.equals("dupes")) {
			this.allowDuplicates = val;
		} else if (currentElement.startsWith("priority")) {
			this.priorities.put(currentElement, val);
		} else if (currentElement.equals("qp")) {
			if (attributeVal.equals("sr")) {
				this.sources.add(val);
			} else {
				this.criteria.addCustomParam(attributeVal, val);
			}
		} else {
			this.criteria.addCustomParam(currentElement, val);
		}
		currentElement = "";
		attributeVal = "";
	}

	/**
	 * Event based parsing -
	 * 
	 * @param ch
	 * @param ch_start
	 * @param ch_length
	 * @exception SAXException
	 */
	public void ignorableWhitespace(char[] ch, int ch_start, int ch_length) throws SAXException {
	}

	/**
	 * Event based parsing -
	 * 
	 * @param uri
	 * @param localName
	 * @param qName
	 * @exception SAXException
	 */
	public void endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName) throws SAXException {
		if (localName.equals("Envelope")) {
			// assemble sources and thesauri
			if (sources.size() > 0) {
				String[] sourcesArr = new String[sources.size()];
				sourcesArr = (String[]) sources.toArray(sourcesArr);
				criteria.setSources(sourcesArr);
			} else {
				criteria.setSources(new String[] { "edna" });
			}

			if (thesauri.size() > 0) {
				String[] thesauriArr = new String[thesauri.size()];
				thesauriArr = (String[]) thesauri.toArray(thesauriArr);
				criteria.setThesauri(thesauriArr);
			}
		}

		if (localName.equalsIgnoreCase("explainRequest")) {
			this.operation = OPERATION_EXPLAIN;
		}
		if (localName.equalsIgnoreCase("searchRetrieve")) {
			this.operation = OPERATION_SEARCHRETRIEVE;
		}
	}

	/**
	 * Event based parsing -
	 * 
	 * @param target
	 * @param data
	 * @exception SAXException
	 */
	public void processingInstruction(String target, String data) throws SAXException {
	}

	/**
	 * Event based parsing -
	 * 
	 * @param uri
	 * @param localName
	 * @param qName
	 * @param attr
	 * @exception SAXException
	 */
	public void startElement(java.lang.String uri, java.lang.String localName, java.lang.String qName, Attributes attr) throws SAXException {
		this.currentElement = localName;
		if (null != attr) {
			this.attributeVal = attr.getValue("name");
		}
	}

}
